﻿
namespace Mulala.Cavan.Presentation.Seedwork
{
    using System;
    using System.Collections.Generic;
    using System.Diagnostics.Contracts;
    using System.Linq;
    using System.Threading;
    using System.Web.Mvc;
    using Mulala.Cavan.Core.Extension;

    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
    public class ActionLoggerAttribute
        : FilterAttribute, IActionFilter, IExceptionFilter, IAuthorizationFilter, IResultFilter
    {
        #region IActionFilter Members
        public virtual void OnActionExecuting(ActionExecutingContext filterContext)
        {
            this.Log().Debug(
                "OnActionExecuting: Action started URI: {0}".FormatWith(
                    filterContext.HttpContext.Request.
                        Url.AbsoluteUri));
        }

        public virtual void OnActionExecuted(ActionExecutedContext filterContext)
        {
            this.Log().Debug(
                "OnActionExecuted: Action finished URI: {0}".FormatWith(
                    filterContext.HttpContext.Request.
                        Url.AbsoluteUri));
        }
        #endregion

        #region IAuthorizationFilter Members
        public virtual void OnAuthorization(AuthorizationContext filterContext)
        {
            this.Log().Info("------------ START ------------");
            this.Log().Info("----" + filterContext.ActionDescriptor.ActionName + "----");
            this.Log().Info("----" + filterContext.ActionDescriptor.ControllerDescriptor.ControllerName + "----");

            this.Log().Debug("OnAuthorization: URI: {0}".FormatWith(filterContext.HttpContext.Request.Url.AbsoluteUri));
            if (filterContext.Result is HttpUnauthorizedResult)
            {
                // unathorized
                this.Log().Error(
                    "OnAuthorization: User '{0}' was NOT authorized ".FormatWith(
                        Thread.CurrentPrincipal.
                            Identity.Name));
            }
            else
            {
                // OK
                this.Log().Info("OnAuthorization: authorized " + Thread.CurrentPrincipal.Identity.Name);
            }
        }
        #endregion

        #region IExceptionFilter Members
        public virtual void OnException(ExceptionContext filterContext)
        {
            this.Log().Fatal("OnException: exception was thrown", filterContext.Exception);
            if (filterContext.Exception.InnerException.Is())
            {
                this.Log().Fatal("OnException: InnerException ", filterContext.Exception.InnerException);
            }
        }
        #endregion

        #region IResultFilter Members
        public virtual void OnResultExecuting(ResultExecutingContext filterContext)
        {
            this.Log().Debug(
                "OnResultExecuting: Action started URI: {0}".FormatWith(
                    filterContext.HttpContext.Request.
                        Url.AbsoluteUri));
        }

        public virtual void OnResultExecuted(ResultExecutedContext filterContext)
        {
            this.Log().Debug(
                "OnResultExecuted: Action finished URI: {0}".FormatWith(
                    filterContext.HttpContext.Request.
                        Url.AbsoluteUri));
            var session = filterContext.HttpContext.Session;
            var bytes = 0;
            foreach (var obj in session)
            {
                bytes += filterContext.ToByteArray(session[obj.ToString()]).Length;
            }
            if (bytes > 500000)
            {
                this.Log().Warn("OnResultExecuted Session Size TOO HIGH: {0} KB ".FormatWith(bytes / 1000));
            }
            else
            {
                this.Log().Info("OnResultExecuted Session Size is OK: {0} KB ".FormatWith(bytes / 1000));
            }
        }
        #endregion
    }
}